﻿Imports System.ComponentModel

Public MustInherit Class ViewModelBase
    Implements INotifyPropertyChanged

#Region "Events"
    Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
#End Region

#Region "Properties"
#Region "Constants"
    ' Insert Constant Declarations Here
#End Region

    Private ReadOnly _commands As _CommandBucket
    Public ReadOnly Property Commands As IDictionary(Of String, IViewModelCommand)
        Get
            Return _commands
        End Get
    End Property

    Private _viewNavigator As IViewNavigator
    Public Property ViewNavigator() As IViewNavigator
        Get
            Return _viewNavigator
        End Get
        Set(ByVal value As IViewNavigator)
            _viewNavigator = value
        End Set
    End Property

#End Region

#Region "Constructors"
    Public Sub New(viewNavigator As IViewNavigator)
        Me.ViewNavigator = viewNavigator
        _commands = New _CommandBucket(Me.ViewNavigator.CommandFactory)
    End Sub
#End Region

#Region "Methods"
    Friend Sub AddCommand(commandName As String, ByVal executeCallback As Action(Of Object))
        _commands.AddCommand(commandName, executeCallback)
    End Sub

    Friend Sub AddCommand(commandName As String, ByVal executeCallback As Action(Of Object), executable As Boolean)
        _commands.AddCommand(commandName, executeCallback, executable)
    End Sub

#Region "Event Raiser Methods"
    Protected Sub OnPropertyChanged(e As PropertyChangedEventArgs)
        RaiseEvent PropertyChanged(sender:=Me, e:=e)

        For Each l_propertyName In PropertyDependencyAttribute.GetDependentPropertyNames(Me.GetType(), e.PropertyName)
            If Not String.Equals(l_propertyName, e.PropertyName) Then
                OnPropertyChanged(l_propertyName)
            End If
        Next
    End Sub

    Protected Sub OnPropertyChanged(propertyName As String)
        OnPropertyChanged(New PropertyChangedEventArgs(propertyName))
    End Sub

    ''' <summary>
    ''' When called from within a property's setter or getter, raises the <see cref="PropertyChanged"/> event for that
    ''' property.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub OnPropertyChanged()
        Dim l_stack = New StackTrace(skipFrames:=1, fNeedFileInfo:=False)
        Dim l_frame = l_stack.GetFrame(0)
        Dim l_methodName = l_frame.GetMethod().Name
        If l_methodName.StartsWith("set_") OrElse l_methodName.StartsWith("get_") Then
            OnPropertyChanged(l_methodName.Substring(4))
        End If
    End Sub
#End Region

#Region "Event Handlers"
    ' Insert Method Declarations which Handle an Event Here
#End Region
#End Region

    Private Class _CommandBucket
        Inherits Dictionary(Of String, IViewModelCommand)

#Region "Events"
        ' Insert Event Declarations Here
#End Region

#Region "Properties"
#Region "Constants"
        ' Insert Constant Declarations Here
#End Region

        Private Property CommandFactory As ICommandFactory
#End Region

#Region "Constructors"
        Public Sub New(commandFactory As ICommandFactory)
            Me.CommandFactory = commandFactory
        End Sub
#End Region

#Region "Methods"
        Friend Sub AddCommand(commandName As String, ByVal executeCallback As Action(Of Object))
            Me.Add(commandName, Me.CommandFactory.CreateCommand(executeCallback, True))
        End Sub

        Friend Sub AddCommand(commandName As String, ByVal executeCallback As Action(Of Object), executable As Boolean)
            Me.Add(commandName, Me.CommandFactory.CreateCommand(executeCallback, executable))
        End Sub

#Region "Event Raiser Methods"
        ' Insert Method Declarations which Raise an Event Here
#End Region

#Region "Event Handlers"
        ' Insert Method Declarations which Handle an Event Here
#End Region
#End Region

    End Class


End Class
